package com.learn.WordAnalysis;


import lombok.Data;

import java.util.LinkedList;
import java.util.Objects;

@Data
public class Analysis {
    boolean flag;

    /**
     * 用以对输入字符串进行转换成符合lr1分析器的字符串 输入字符以空格隔开
     * @param inputStr
     * @return
     */
    public String analysisString(String inputStr){

        flag=true;

        /**
         * G=(Vn,Vt,S,P)
         * Vn={E,S,W,s,d}
         * Vt={+,-,=,i,<,>,w,o,O,A,N,;,(,),j,k}
         * P={S->ds,d->WEo,W->w,E->E<E,E->E>E,E->i,s->i=E,E->E+E,E->E-E,E->EOE,E->EAE,E->NE,s->s;s,E->(E),E->j,E->k}
         * S=S
         */

        String[] strings = inputStr.split(" ");
        LinkedList<String> outPutList=new LinkedList<>();
        String outPutString="";

        int i=0;

        for (String str:strings){
            if(Objects.equals(str, "+")||Objects.equals(str, "-")||Objects.equals(str, "=")
                    ||Objects.equals(str, "<")||Objects.equals(str, ">")
                    ||Objects.equals(str, ";")||Objects.equals(str, "(")
                    ||Objects.equals(str, ")")||Objects.equals(str, "k")){
                outPutList.add(str);
            }
            else if(Objects.equals(str, "while")){
                outPutList.add("w");
            }
            else if(Objects.equals(str, "do")){
                outPutList.add("o");
            }
            else if(Objects.equals(str, "or")){
                outPutList.add("O");
            }
            else if(Objects.equals(str, "and")){
                outPutList.add("A");
            }
            else if(Objects.equals(str, "not")){
                outPutList.add("N");
            }else{
                //获取第一个字符
                char frist=str.toCharArray()[0];

                //判断是否为标识符
                if(((frist>='a'&&frist<='z')||(frist>='A'&&frist<='Z')||frist=='_'||frist=='$')){
                    if(isID(str)){
                        outPutList.add("i");
                    }
                }else if(frist>='0'&&frist<='9'){
                    double flag=analysisNUM(str);
                    if(flag!=-1){
                        outPutList.add("k");
                    }else {
                        System.out.println("输入的第"+i+"个字符"+strings[i]+"非法");
                        this.flag=false;
                    }

                }else {
                    System.out.println("输入的第"+i+"个字符"+strings[i]+"非法");
                    this.flag=false;
                }

            }

            i++;
        }
        outPutList.add("#");
        for (String str:outPutList){
            outPutString+=str;
        }
        return outPutString;
    }

    public boolean isID(String str){
        int i=0;
        char[] chars=str.toCharArray();

        if(!((chars[i]>='a'&&chars[i]<='z')||(chars[i]>='A'&&chars[i]<='Z')||chars[i]=='_'||chars[i]=='$')){
            return false;
        }

        for(i=1;i<chars.length;i++){
            if(!((chars[i]>='a'&&chars[i]<='z')||(chars[i]>='A'&&chars[i]<='Z')||chars[i]=='_'||chars[i]=='$'||(chars[i]>='0'&&chars[i]<='9'))){
                return false;
            }
        }

        return true;
    }

    public double analysisNUM(String str){
        char[] chars=str.toCharArray();
        double result;
        int P=0,j=0,e=1;
        result=chars[0]-48;
        int i=0;
        for(i=1;i<str.length();i++){
            //整数部分如果是数字则继续
            if(chars[i]>='0'&&chars[i]<='9'){
                result=result*10+chars[i]-48;
                continue;
            }else{
                //如果不是数字则进入小数部分分析
                return analysisDecimal(result,i,chars,e,P,j);
            }
        }
        return result;
    }

    //分析小数部分
    public double analysisDecimal(double N,int i,char[] chars,int e,int P,int j){
        if(chars[i]!='.'){
            //如果不是小数点进入指数部分分析
            return analysisIndex(N,i,chars,e,P,j);
        }
        i++;
        if(!(chars[i]>='0'&&chars[i]<='9')){
            //如果不是数字返回错误
            N=-1;
            return N;
        }
        for(;i<chars.length;i++){
            if(chars[i]>='0'&&chars[i]<='9'){
                N=N*10+chars[i]-48;
                j++;
            }else {
                return analysisIndex(N,i,chars,e,P,j);
            }
        }
        //当小数点后面全是数字时进入指数分析
        return analysisIndex(N,i-1,chars,e,P,j);
        //return N*Math.pow(10,(double) e*P-j);
    }


    //分析指数部分
    public double analysisIndex(double N,int i,char[] chars,int e,int P,int j){
        int d=0;
        if(chars[i]=='e'){
            i++;
            if(chars[i]=='-'){
                e=-1;
                i++;
            }else if(chars[i]=='+'){
                i++;
            }
            if(chars[i]>='0'&&chars[i]<='9'){
                d=chars[i]-48;
                P=P*10+d;
                i++;
                for(;i<chars.length;i++){
                    if(chars[i]>='0'&&chars[i]<='9'){
                        d=chars[i]-48;
                        P=P*10+d;
                    }else {
                        N=-1;
                        return N;
                    }
                }
            }else {
                N=-1;
                return N;
            }
        }else if(!(chars[i]>='0'&&chars[i]<='9')){
            return -1;
        }
        return N*Math.pow(10,(double) e*P-j);
    }
}
